#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define offset_of(TYPE, MEMBER) ((size_t) &((TYPE*)0)->MEMBER)

/**
 * @brief  container_of()
 * @note   
 * @param [in] ptr 成员指针
 * @param [in] type 结构体 比如struct __student_
 * @param [in] member 成员变量，跟指针对应
 * @param [out]
 * @retval 
 */
#define container_of(ptr, type, member) ({          \
        const typeof( ((type *)0)->member ) *__mptr = (const typeof( ((type *)0)->member ) *)(ptr); \
        (type *)( (char *)__mptr - offset_of(type, member) );})

typedef struct __student_{
    char name[16];
    int age;
    int id;
    unsigned long phone_num;
    char *info;
} student_t;

void print_student_info(void *p_info)
{
    student_t *p = NULL;
    p = (student_t*)p_info;

    printf("addr=%p name:%s\n",&p->name, p->name);
    printf("addr=%p age:%d\n",&p->age,  p->age);
    printf("addr=%p id:%d\n", &p->id, p->id);
    printf("addr=%p phone_num:%ld\n", &p->phone_num, p->phone_num);
    printf("addr=%p info:%s\n", p->info, p->info);
    printf("\n");
}

/**
 * @brief  
 * @note   
 * @param [in]
 * @param [out]
 * @retval 
 */
int container_of_demo1(void)
{
    student_t *m_stu = (student_t*)malloc(sizeof(student_t));

    // 赋初值
    m_stu->age = 25;
    m_stu->id = 1;
    memcpy(m_stu->name, "sumu", sizeof(m_stu->name));
    m_stu->phone_num = 123456;
    m_stu->info = "aaaa";
    print_student_info(m_stu);
    
    student_t * p_student = NULL;
    p_student = container_of(&m_stu->id, struct __student_, id);
    printf("p_student=%p id=%p\n",p_student, &m_stu->id);
    print_student_info(p_student);

    p_student = container_of(&m_stu->info, struct __student_, info);
    printf("p_student=%p info=%p &info=%p\n",p_student, m_stu->info, &m_stu->info);
    print_student_info(p_student);

    p_student = container_of(m_stu->name, struct __student_, name);
    printf("p_student=%p name=%p &name=%p\n",p_student, m_stu->name, &m_stu->name);
    print_student_info(p_student);

    if (m_stu != NULL)
    {
        free(m_stu);
    }

    return 0;
}

int main(int argc, const char *argv[])
{
    int ret = 0;
    /* code */

    ret = container_of_demo1();

    return ret;
}